chore: sync workflow templates - #607
Conversation
Automated sync from stranske/Workflows Template hash: 2e01e11c7edc Changes synced from sync-manifest.yml
🤖 Keepalive Loop StatusPR #607 | Agent: Codex | Iteration 0/5 Current State
🔍 Failure Classification| Error type | infrastructure | |
Keepalive Work Log (click to expand)
|
There was a problem hiding this comment.
Pull request overview
This PR syncs workflow templates and metrics tooling from stranske/Workflows, extending weekly metrics collection with richer artifact-download accounting, machine-readable summary contracts, and expanded terminal-disposition/bot-auth coverage reporting.
Changes:
- Add a weekly metrics artifact download manifest (JSON + markdown) and publish a machine-readable aggregated metrics contract alongside the markdown summary.
- Expand terminal disposition coverage to include verifier-model compatibility checks and surface priority artifact-family status in reports.
- Emit a wrapper terminal-disposition record from the bot-comment-handler wrapper workflow and enrich PR meta preamble with source-issue closing metadata.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
scripts/aggregate_agent_metrics.py |
Enriches NDJSON parsing with source metadata, detailed parse errors, verifier-model stats, and outputs a JSON summary contract. |
.github/workflows/agents-weekly-metrics.yml |
Generates and uploads selection + download-manifest artifacts; produces both markdown and JSON weekly metrics outputs. |
.github/workflows/agents-bot-comment-handler.yml |
Adds skip-reason output and emits/uploads a wrapper terminal-disposition NDJSON + markdown summary. |
.github/workflows/agents-81-gate-followups.yml |
Switches keepalive metrics JSON emission to compact (jq -cn) output suitable for NDJSON usage. |
.github/scripts/weekly_metrics_download_manifest.js |
New utility to initialize/record/finalize a structured artifact download manifest and render it as markdown. |
.github/scripts/weekly_metrics_artifacts.js |
Adds “missing priority families” and per-priority-family status details to the artifact selection report/markdown. |
.github/scripts/terminal_disposition_coverage.js |
Adds verifier-model compatibility summary and improved artifact-selection normalization/markdown output. |
.github/scripts/terminal_disposition.js |
Adds normalized fields for llm_model, model_selection_reason, and verifier_mode on terminal disposition records. |
.github/scripts/coverage_monitor_summary.js |
New weekly coverage monitor contract summarizing terminal + bot-auth coverage reports. |
.github/scripts/bot_comment_auth_coverage.js |
Adds reusable-invocation expectation fields and richer organic-evidence reporting (skipped/missing requirements). |
.github/scripts/agents_pr_meta_update_body.js |
Adds an issue metadata marker and “Closes #…” line to the PR preamble when a source issue is present. |
| file_entries: list[dict[str, Any]] = [] | ||
| file_errors: list[ParseErrorDetail] = [] | ||
| raw_lines: list[str] = [] | ||
| with handle: | ||
| for line in handle: | ||
| for line_number, line in enumerate(handle, start=1): | ||
| raw = line.strip() | ||
| if not raw: | ||
| continue | ||
| raw_lines.append(raw) | ||
| try: |
There was a problem hiding this comment.
In _read_ndjson, raw_lines is populated for every non-empty line even when the file is valid NDJSON. For larger artifacts this duplicates the entire file content in memory unnecessarily. Consider only collecting raw_lines when you actually need the whole-file fallback parse (e.g., only while file_entries is still empty and a parse error has been observed, and/or cap the number of collected lines).
| def _parse_error_contract(parse_error_details: list[ParseErrorDetail]) -> dict[str, Any]: | ||
| family_counts = Counter(detail.artifact_family for detail in parse_error_details) | ||
| artifact_counts = Counter(detail.artifact for detail in parse_error_details) | ||
| reason_counts = Counter(detail.reason for detail in parse_error_details) | ||
| return { | ||
| "count": len(parse_error_details), | ||
| "by_artifact_family": dict(sorted(family_counts.items())), | ||
| "by_artifact": dict(sorted(artifact_counts.items())), | ||
| "by_reason": dict(sorted(reason_counts.items())), | ||
| "details": [detail.as_dict() for detail in parse_error_details], | ||
| } |
There was a problem hiding this comment.
_parse_error_contract includes a details array containing every parse error. Combined with _read_ndjson recording an error per bad line, a single corrupted/large input can produce a very large JSON summary (and high memory usage). Consider bounding details (and/or the collected parse errors) and adding an omitted_count/truncated indicator so the contract remains safe to upload and consume.
| - name: Write wrapper terminal disposition | ||
| if: always() | ||
| env: | ||
| RESOLVED_PR_NUMBER: ${{ steps.resolve.outputs.pr_number }} | ||
| REUSABLE_INVOCATION_EXPECTED: ${{ steps.resolve.outputs.should_run }} | ||
| SKIP_REASON: ${{ steps.resolve.outputs.skip_reason }} | ||
| run: | | ||
| mkdir -p agent-metrics | ||
| node <<'NODE' | ||
| const fs = require('fs'); | ||
| const helperPath = './.github/scripts/terminal_disposition.js'; |
There was a problem hiding this comment.
This job runs ./.github/actions/setup-api-client (which executes node/npm) and later runs an inline node script, but the workflow doesn't set up a pinned Node version first. Other workflows in this repo run actions/setup-node (Node 20) before setup-api-client to avoid relying on whatever Node happens to be preinstalled on ubuntu-latest. Add a Setup Node step (pinned SHA) before Setup API client/the node <<'NODE' invocation.
| status: selectedCount > 0 ? 'selected' : (candidateCount > 0 ? 'available' : 'missing'), | ||
| candidate_count: candidateCount, | ||
| selected_count: selectedCount, | ||
| latest_candidate: selectedArtifact ? normalizeSelectionArtifact(selectedArtifact) : null, |
There was a problem hiding this comment.
In the backward-compatibility branch of normalizeTerminalPriorityFamilyStatuses, latest_candidate is set from selectedArtifact (and is left null when only candidates exist but nothing selected). This makes the field semantically misleading and can hide useful “latest available” info. Consider leaving latest_candidate null in this fallback (or deriving it from report.priority_family_statuses/other available metadata) and only populating selected_artifact from selectedArtifact.
| latest_candidate: selectedArtifact ? normalizeSelectionArtifact(selectedArtifact) : null, | |
| latest_candidate: null, |
Sync Summary
Files Updated
Files Skipped
Review Checklist
Source: stranske/Workflows
Manifest:
.github/sync-manifest.yml